<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 一：
        // let a = 3
        // let b = new Number(3)
        // let c = 3

        // console.log(a == b)         // true
        // console.log(a === b)        // false
        // console.log(b === c)        // false

        // // == 等值符 仅判断值是否相等（先转化为相同类型再进行值的比较）
        // // === 等同符 不仅判断值是否相等，还判断数据类型是否相同（先比较类型再比较值）
        // console.log(a);
        // console.log(b); // Number {3}
        // console.log(c);
        // new Number() 是一个内建的函数构造器。不是一个真实的 number：它有一堆额外的功能并且它是一个对象。

        // 二：
        // class Chameleon {
        //     static colorChange(newColor) {
        //         this.newColor = newColor
        //         return this.newColor
        //     }

        //     constructor({ newColor = 'green' } = {}) {
        //         this.newColor = newColor
        //     }
        // }

        // const freddie = new Chameleon({ newColor: 'purple' })
        // // freddie.colorChange('orange')
        // // colorChange 是一个静态方法。静态方法被设计为只能被创建它们的构造器使用（也就是 Chameleon），并且不能传递给实例。
        // // 因为 freddie 是一个实例，静态方法不能被实例使用，因此抛出了 TypeError 错误。
        // // 构建静态方法的类调用：
        // console.log(Chameleon.colorChange('blue'))
        // // 同时父类的静态方法，可以被子类继承
        // class child extends Chameleon {
        //     constructor() {
        //         super();
        //     }
        // }
        // console.log(child.prototype)
        // console.log(child.colorChange('pink'))

        // 三：
        // let greeting
        // greetign = {} // Typo!
        // console.log(greetign)
        // 代码打印出了一个对象，这是因为我们在全局对象上创建了一个空对象！当我们将 greeting 写错成 greetign 时，JS 解释器实际在上浏览器中将它视为 global.greetign = {} （或者 window.greetign = {}）。
        // 为了避免这个为题，我们可以使用 `"use strict"ES5严格模式。这能确保当你声明变量时必须赋值。

        // 四：
        // function bark() {
        //     console.log('Woof!')
        // }

        // bark.animal = 'dog';
        // bark.say = function() {
        //     console.log('Cat!')
        // }
        // bark();     // WOOF
        // bark.say(); // CAT
        // 函数正常运行，不会报错，这在 JavaScript 中是可以的，因为函数是对象！（除了基本类型之外其他都是对象）
        // 函数是一个特殊的对象。你写的这个代码其实不是一个实际的函数。函数是一个拥有属性的对象，并且属性也可被调用

        // 五：
        // function Person(firstName, lastName) {
        //     this.firstName = firstName;
        //     this.lastName = lastName;
        //     // 解决方式一：直接在构造函数中添加
        //     // this.getFullName = function () {
        //     //     return `${this.firstName} ${this.lastName}`;
        //     // }
        // }

        // // const member = new Person("Lydia", "Hallie");

        // Person.getFullName = function () {
        //     return `${this.firstName} ${this.lastName}`;
        // }

        // console.log(member.getFullName());  // 报错，TypeError
        // 有时候不是每个 Person 实例都需要这个方法。这将浪费大量内存空间，因为它们仍然具有该属性，这将占用每个实例的内存空间。
        // 相反，如果我们只将它添加到原型中，那么它只存在于内存中的一个位置，但是所有实例都可以访问它！
        // 正确方式：
        // Person.prototype.getFullName = function () {
        //     return `${this.firstName} and ${this.lastName}`;
        // }
        // console.log(member.getFullName());  

        // 六：   
        function Person(firstName, lastName) {
            this.firstName = firstName
            this.lastName = lastName
        }

        const lydia = new Person('Lydia', 'Hallie')
        const sarah = Person('Sarah', 'Smith')

        console.log(lydia)   // Person {firstName: "Lydia", lastName: "Hallie"}
        console.log(sarah)   // undefined

        // 对于 sarah，我们没有使用 new 关键字。当使用 new 时，this 引用我们创建的空对象。
        // 当未使用 new 时，this 引用的是全局对象（global object）。
        // 我们说 this.firstName 等于 "Sarah"，并且 this.lastName 等于 "Smith"。
        // 实际上我们做的是，定义了 global.firstName = 'Sarah' 和 global.lastName = 'Smith'。而 sarah 本身是 undefined。
    </script>
</body>
</html>